package end.util.jedis;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang3.SerializationUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;

/**
 * 
 * ShiroRedisSessionDAO 上午9:01:02 Copyright HEXUNz Inc. All right reserved.
 * Email : alldios@outlook.com
 * 
 */
public class ShiroRedisSessionDAO extends AbstractSessionDAO {
	private static Logger logger = LogManager.getLogger(ShiroRedisSessionDAO.class);

	@Override
	public void update(Session session) throws UnknownSessionException {
		this.saveSession(session);
	}

	private void saveSession(Session session) throws UnknownSessionException {
		if (logger.isDebugEnabled()) {
			logger.debug("保存session {} ：  +" + session.getId());
		}
		if (session == null || session.getId() == null) {
			logger.error("session or session id is null");
			return;
		}
		byte[] key = this.getByteKey(session.getId());
		byte[] value = SerializationUtils.serialize((Serializable) session);
		session.setTimeout(shiroRedisWorker.getExpire());
		this.shiroRedisWorker.set(key, value, shiroRedisWorker.getExpire());
	}

	@Override
	public void delete(Session session) {
		if (session == null || session.getId() == null) {
			logger.error("session or session id is null");
			return;
		}
		shiroRedisWorker.del(this.getByteKey(session.getId()));
	}

	@Override
	public Collection<Session> getActiveSessions() {
		Set<Session> sessions = new HashSet<Session>();
		Set<byte[]> keys = shiroRedisWorker.keys(this.keyPrefix + "*");
		if (keys != null && keys.size() > 0) {
			for (byte[] key : keys) {
				Session s = (Session) SerializationUtils
						.deserialize(shiroRedisWorker.get(key));
				sessions.add(s);
			}
		}
		return sessions;
	}

	@Override
	protected Serializable doCreate(Session session) {
		Serializable sessionId = this.generateSessionId(session);
		this.assignSessionId(session, sessionId);
		this.saveSession(session);
		return sessionId;
	}

	@Override
	protected Session doReadSession(Serializable sessionId) {
		if (sessionId == null) {
			logger.error("session id is null");
			return null;
		}
		Session s = null;
		try {
			s = (Session) SerializationUtils.deserialize(shiroRedisWorker
					.get(this.getByteKey(sessionId)));
			return s;
		} catch (Exception e) {
			return s;
		}
	}

	private byte[] getByteKey(Serializable sessionId) {
		String preKey = this.keyPrefix + sessionId;
		return preKey.getBytes();
	}

	private ShiroRedisWorker shiroRedisWorker;
	private String keyPrefix = "shiro_redis_session:";

	public String getKeyPrefix() {
		return keyPrefix;
	}

	public void setKeyPrefix(String keyPrefix) {
		this.keyPrefix = keyPrefix;
	}

	public ShiroRedisWorker getShiroRedisWorker() {
		return shiroRedisWorker;
	}

	public void setShiroRedisWorker(ShiroRedisWorker shiroRedisWorker) {
		this.shiroRedisWorker = shiroRedisWorker;
	}
}